1 Apresentação

Olá sou Marcello Filgueiras, faço Direito na UFJF (Universidade Federal de Juiz de Fora), e me interesso por Jurimetria. Minha ideia é baixar dados de tribunais para fazer pesquisa acadêmica, mas também estou tentando entrar com consultoria jurídica em mercado da jurimetria.

O objetivo desse scrapper é baixar a jurisprudência, o conjunto de decisões do TRF-5, o Tribunal Regional Federal do Nordeste, bem como a consulta processual de cada um dos processos específicos, que irá buscar metadados do processo, suas partes e as respectivas movimentações.

Portanto, são dois scrappers: Um do buscador de jurisprudência, outro da consulta processual.

Aqui estão os pacotes usados nesse processo.

knitr::opts_chunk$set(echo = TRUE)

#mais na primeira
library(tidyverse)
library(httr)
library(abjutils)
library(jsonlite)

#Mais a segunda
library(xml2)
library(rvest)
library(lubridate)

2 Buscador de Jurisprudência

Trata-se de um buscador de julgados que vai te retornar decisões dos tribunais, a partir de uma pesquisa em texto, possibilitando de filtrar por orgão julgador, por relator que redigiu o acórdão ou por período de tempo. Por fim, ainda, é possível buscar diretamente o julgado com o número do processo específico.

Apesar de parecer uma requisição POST, o site leva a uma API escondida que utiliza requisições GET. Os dados vêm em json, o que possibilita muito menos trabalho no parsing.

2.1 Acessando a API escondida

Parece um POST por ser um formulário, mas leva a uma API que dá .json, por meio de um GET, que tem a seguinte URL base.

url_base <- "https://julia-pesquisa.trf5.jus.br/julia-pesquisa/api/documentos:dt?"

2.1.1 Teste Super Específico

Ao fazer uma pesquisa na Jurisprudência pelo texto de “28,86%” em referência a uma tese consolidada sobre direito aumento de salários de professores federais no montante de 28,86%, do Relator Alcides Saldanha Lima, da 3ª Turma recursal, num espaço de 10 anos.

Nos headers, estes são os parâmetros que retornam do navegador:

Dentro da query, essa busca pode ser feita com {httr}.

query_teste_especifico<- list(
  "draw" = "1",
  "columns[0][data]" = "codigoDocumento",
  "columns[0][name]" = "",
  "columns[0][searchable]" = "true",
  "columns[0][orderable]" = "false",
  "columns[0][search][value]" = "",
  "columns[0][search][regex]" = "false",
  "start" = "0",
  "length" = "10",
  "search[value]" = "",
  "search[regex]" = "false",
  "pesquisaLivre" = "28,86%",
  "numeroProcesso" = "",
  "orgaoJulgador" = "3ª TURMA",
  "relator" = "ALCIDES SALDANHA LIMA",
  "dataIni" = "01/01/2010",
  "dataFim" = "03/10/2021",
  "_" = "1633297312330")

teste_especifico <- httr::GET(url_base, 
                      query =query_teste_especifico)

# Vendo o resultado, temos um Json, com dados em Listas.

content(teste_especifico) %>%
  str(max=2)
## List of 6
##  $ draw           : int 1
##  $ recordsTotal   : int 1
##  $ recordsFiltered: int 1
##  $ data           :List of 1
##   ..$ :List of 31
##  $ error          : NULL
##  $ criteria       : chr "expressão: \"28,86%\", relator: ALCIDES SALDANHA LIMA, julgamento/publicação entre 01/01/2010 e 03/10/2021, órg"| __truncated__

Podemos ver então que, de início, conseguimos baixar todos os processos, com parâmetros bem definidos, nos seguintes parâmeteros:

Parâmetro Dados Buscados
“pesquisaLivre” “28,86%”,
“numeroProcesso” "",
“orgaoJulgador” “3? TURMA”,
“relator” “ALCIDES SALDANHA LIMA”,
“dataIni” “01/01/2010”,
“dataFim” “03/10/2021”,

Esses headers respondem, portanto, ao que colocamos no buscador. O que fazem os outros parâmetros, especialmente para paginação?

Poderíamos saber, mas essa busca retornou apenas um julgado. Vamos então para quantidades maiores de julgados, com uma requisição mais genérica.

Mas os dados estão dentro do elemento de nome “data”.

2.1.2 Teste Genérico

Nesse teste, procuramos somente pelo testo “28,86%”:

query_teste_generico <- list(
  "draw" = "1",
  "columns[0][data]" = "codigoDocumento",
  "columns[0][name]" = "",
  "columns[0][searchable]" = "true",
  "columns[0][orderable]" = "false",
  "columns[0][search][value]" = "",
  "columns[0][search][regex]" = "false",
  "start" = "0",
  "length" = "10",
  "search[value]" = "",
  "search[regex]" = "false",
  "pesquisaLivre" = "28,86%",
  "numeroProcesso" = "",
  "orgaoJulgador" = "",
  "relator" = "",
  "dataIni" = "",
  "dataFim" = "",
  "_" = "1633297312330")


teste_generico <- httr::GET(url_base, 
                              query = query_teste_generico)


content(teste_generico)%>%
  str(max=2)
## List of 6
##  $ draw           : int 1
##  $ recordsTotal   : int 9101
##  $ recordsFiltered: int 9101
##  $ data           :List of 10
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##  $ error          : NULL
##  $ criteria       : chr "expressão: \"28,86%\""

Temos 9000 julgados, com 10 por página. Vamos então trocar de página para ver o que acontece:

Página 1: Start = 0, Draw = 1

Página 2: Start = 10, Draw = 2

Página 3: Start = 20, Draw = 3

Sabemos, portanto, que aumentando o parâmetro start, ele vai começar a exibir a partir dos próximos 10 julgados. Ele também registra no draw qual número de páginas que você está (na verdade, quantas você trocou). Ao final um parâmetro underline misterioso que registra, ao que parece, o número de vezes que uma requisição foi pedida no site. Ele sobe progressivamente, mas se você acessa o site. Estamos chegando na forma de saber como a API funciona.

Última questão. Os parâmetro draw e underline misterioso podem ser retirados?

O draw não pode ser retirado, retorna erro:

 httr::GET(url_base,
      query = list(
  "columns[0][data]" = "codigoDocumento",
  "columns[0][name]" = "",
  "columns[0][searchable]" = "true",
  "columns[0][orderable]" = "false",
  "columns[0][search][value]" = "",
  "columns[0][search][regex]" = "false",
  "start" = "0",
  "length" = "10",
  "search[value]" = "",
  "search[regex]" = "false",
  "pesquisaLivre" = "28,86%",
  "numeroProcesso" = "",
  "orgaoJulgador" = "",
  "relator" = "",
  "dataIni" = "",
  "dataFim" = "",
  "_" = "1633297312330")) %>%
  content()
## $status
## [1] 400
## 
## $mensagem
## [1] "Required long parameter 'draw' is not present"

Mas o misterioso underline com número pode sumir:

 httr::GET(url_base,
      query = list(
  "draw" = "1",
  "columns[0][data]" = "codigoDocumento",
  "columns[0][name]" = "",
  "columns[0][searchable]" = "true",
  "columns[0][orderable]" = "false",
  "columns[0][search][value]" = "",
  "columns[0][search][regex]" = "false",
  "start" = "0",
  "length" = "10",
  "search[value]" = "",
  "search[regex]" = "false",
  "pesquisaLivre" = "28,86%",
  "numeroProcesso" = "",
  "orgaoJulgador" = "",
  "relator" = "",
  "dataIni" = "",
  "dataFim" = "")) %>%
  content() %>%
  str(max=2)
## List of 6
##  $ draw           : int 1
##  $ recordsTotal   : int 9101
##  $ recordsFiltered: int 9101
##  $ data           :List of 10
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##   ..$ :List of 31
##  $ error          : NULL
##  $ criteria       : chr "expressão: \"28,86%\""

Vamos então criar a função para baixar os dados!

2.2 Baixando e Iterando

Se temos 10 processos por página e um universo de 9000 julgados, é só iterar a função 900 vezes com starts diferentes, 0, 10 e 20 e assim vai. O parâmetros draw poderiam ser de 1, 2 e 3, mas só com o 1 funciona, acredito que sendo interpretado como a primeira página que você acessa, so que com o starts diferente.

trf5_baixar_cjsg <- function(pesquisa_livre = "", orgao_julgador = "",
                             relator = "", data_inicial = "", data_final = "",
                             diretorio = "") {
  # Vamos ter a url_base
  url_base <- "https://julia-pesquisa.trf5.jus.br/julia-pesquisa/api/documentos:dt?"
  
  # Vamos baixar a primeira página.
  query_1 = list(
    "draw" = "1",
    "columns[0][data]" = "codigoDocumento",
    "columns[0][name]" = "",
    "columns[0][searchable]" = "true",
    "columns[0][orderable]" = "false",
    "columns[0][search][value]" = "",
    "columns[0][search][regex]" = "false",
    "start" = "0",
    "length" = "10",
    "search[value]" = "",
    "search[regex]" = "false",
    "pesquisaLivre" = pesquisa_livre,
    "numeroProcesso" = "",
    "orgaoJulgador" = orgao_julgador,
    "relator" = relator,
    "dataIni" = data_inicial,
    "dataFim" = data_inicial)
  
  # Fazemos uma sequência de página  
 n_observacoes <- httr::GET(url_base,
            query= query_1) %>% 
             content() %>%
             pluck("recordsTotal")
   
  # Pegando o número de starts pela página
 n_starts <- seq(0,n_observacoes,10)
 
 # Fazendo o Map colocando o número de starts de character
 purrr::map(.x= n_starts,
            ~httr::GET(url_base,
                       query= list(
                         "draw" = "1",
                         "columns[0][data]" = "codigoDocumento",
                         "columns[0][name]" = "",
                         "columns[0][searchable]" = "true",
                         "columns[0][orderable]" = "false",
                         "columns[0][search][value]" = "",
                         "columns[0][search][regex]" = "false",
                         "start" = as.character(.x),
                         "length" = "10",
                         "search[value]" = "",
                         "search[regex]" = "false",
                         "pesquisaLivre" = pesquisa_livre,
                         "numeroProcesso" = "",
                         "orgaoJulgador" = orgao_julgador,
                         "relator" = relator,
                         "dataIni" = data_inicial,
                         "dataFim" = data_final),
          # Fazendo write_disk para salvar na minha pasta
          # nome da pasta é o numero do processo e a data da postagem.
            write_disk(path = paste0(diretorio, 
                                    "/",
                                   "julgados_",
                                  as.character(.x),
                                 "_",
                                Sys.time()%>%
                                 str_replace_all("\\D","_"),
                              ".json"))
            ))
           
 
}

Conseguimos! Essa função baixou os 9000 julgados, mas não rodar no markdown.

trf5_baixar_cjsg(pesquisa_livre = “28,86%”, diretorio = “data_raw”)

9000 páginas baixadas

2.3 Lendo e Iterando

Baixados os julgados, vamos à leitura deles. Como são Json’s limpos, não necessidade de parsing complicado.

Temos que fazer 3 coisas na função, um _purrr::map() que vai ler tudo.

  1. Para criar .x da função, vamos listar quais arquivos estão na pasta, o que foi feito com base::list.files.
  2. Criar a barra de progresso com progress::progress_bar
  3. Ler os Jsons
trf5_ler_cjsg <- function(diretorio= ""){
  
  #Listando os Arquivos
  arquivos <- base::list.files(paste0(diretorio,"/"),
                   pattern = "\\.json$", 
                   full.names = TRUE) 
  #Barra de Progresso
  barra_progresso <- progress::progress_bar $ new(total = length(arquivos))
  
  purrr::map_df( .x= arquivos,
                  .f = ~{
                    barra_progresso$tick()
                    #Lendo e selecionado a lista
                    jsonlite::fromJSON (.x, simplifyDataFrame = TRUE )%>%
                   purrr::pluck("data")
                    })
}

Vamos testar a função:

julgados_28_raw <- trf5_ler_cjsg(diretorio= "cjsg/data_raw") %>%
  janitor::clean_names()

julgados_28_raw%>%
  tibble::as_tibble()
## # A tibble: 9,081 x 31
##    codigo_documento         sistema tipo_documento numero_processo classe_judicial
##    <chr>                    <chr>   <chr>          <chr>           <chr>          
##  1 150990:28021562:27972997 PJE     EMENTA         08032902720154~ APELAÇÃO CÍVEL 
##  2 380241:28021371:27972806 PJE     EMENTA         08077735220214~ AGRAVO DE INST~
##  3 394527:27962733:27914229 PJE     EMENTA         08188979520204~ APELAÇÃO CÍVEL 
##  4 367248:28036519:27987929 PJE     EMENTA         08056975520214~ AGRAVO DE INST~
##  5 277531:27969211:27920709 PJE     EMENTA         00023048220104~ APELAÇÃO / REM~
##  6 348077:27927371:27878904 PJE     EMENTA         08027624220214~ AGRAVO DE INST~
##  7 210311:27925758:27877290 PJE     EMENTA         08125577720184~ AGRAVO DE INST~
##  8 381611:27925176:27876708 PJE     EMENTA         08079545320214~ AGRAVO DE INST~
##  9 376153:27563983:27516214 PJE     EMENTA         08071144320214~ AGRAVO DE INST~
## 10 365466:28157049:28108267 PJE     EMENTA         00115384520114~ APELAÇÃO CÍVEL 
## # ... with 9,071 more rows, and 26 more variables:
## #   numero_sequencial_classe <chr>, sigla_classe <chr>, numero_classe <chr>,
## #   uf_classe <chr>, relator <chr>, revisor <chr>, relator_acordao <chr>,
## #   orgao_julgador <chr>, data_autuacao <chr>, data_julgamento <chr>,
## #   data_assinatura <chr>, ativo <lgl>, ementa <chr>, decisao <chr>,
## #   indexacao <chr>, referencia <chr>, outras_referencias <chr>,
## #   observacao <chr>, url <chr>, referencias_legislativas <list>, ...

Conseguimos! Lemos as bases e estão em um formato pronto para ser utilizado

2.4 Utilizando a Base

No Escritório, o foco está em analisar o tempo que o processo demora. Assie, tentei analisar um tempo que a interposição recurso pode influenciar no julgamento, desde a sua autuação (registro no sistema) até seu julgamento.

2.4.1 Tidying

Vamos ver a qualidade das bases.

Órgão Julgadores estão padronizados:

julgados_28_raw %>%
  count(orgao_julgador)
##     orgao_julgador    n
## 1         1ª TURMA 2338
## 2         2ª TURMA 2045
## 3         3ª TURMA 2588
## 4         4ª TURMA 1183
## 5            PLENO  923
## 6      PRESIDÊNCIA    3
## 7 VICE-PRESIDÊNCIA    1

A Classe de cada Recurso não:

#A Classe de cada Recurso não
julgados_28_raw %>%
  count(classe_judicial) %>%
  as_tibble(max=20)
## # A tibble: 77 x 2
##    classe_judicial                                                 n
##    <chr>                                                       <int>
##  1 AÇÃO RESCISORIA                                               226
##  2 AÇÃO RESCISÓRIA                                               209
##  3 AGRAVO DE INSTRUMENTO                                        1750
##  4 AGRAVO INOMINADO                                                3
##  5 AGRAVO INOMINADO NA AÇÃO RESCISÓRIA                             1
##  6 AGRAVO INOMINADO NA APELAÇÃO CIVEL                             16
##  7 AGRAVO INOMINADO NA REMESSA EX-OFFÍCIO                          1
##  8 AGRAVO INOMINADO NO AGRAVO DE INSTRUMENTO                       7
##  9 AGRAVO INOMINADO NOS EMBARGOS À EXECUÇÃO EM AÇÃO RESCISÓRIA     1
## 10 AGRAVO INONIMADO NA MEDIDA CAUTELAR                             1
## # ... with 67 more rows

Vamos dar um tidying: 1) Passando datas para formato date. 2) padronizando classes. As que não foram usadas e coloquei “#” foi porque tinham número pequeno que não era muito significativo para a operação.

julgados_28_tidy <- julgados_28_raw %>%
  #Passando Formato Date
  mutate(across(.cols = c(data_autuacao, data_julgamento, data_assinatura),
                .fns = lubridate::ymd
                )
         ) %>%
  # Arrumando Duplicidade. os outros # no meio do case_when são categorias que,
  #apesar de serem duplicadas, estavam em baixo número e não era necessária sua apresentação
  mutate(classe_judicial_raw= abjutils::rm_accent(classe_judicial)%>%
                            str_to_lower(),
         classe_judicial= case_when(
           str_detect(classe_judicial_raw, "embargos de declaracao") ~ "Embargos de Declaração",
           #str_detect(classe_judicial_raw, "inominado|inonimado") ~ "Agravo Inominado",
           str_detect(classe_judicial_raw, "regimental") ~ "Agravo Regimental",
           #str_detect(classe_judicial_raw, "agravo n|agravo retido") ~ "Agravo",
           #str_detect(classe_judicial_raw, "agravo interno") ~ "Agravo Interno",
           str_detect(classe_judicial_raw, "agravo de instrumento") ~ "Agravo de Instrumento",
           str_detect(classe_judicial_raw, "remessa|reexame") ~ "Remessa Necessária",
           str_detect(classe_judicial_raw, "embargos a execucao") ~ "Embargos à Execução",
           #str_detect(classe_judicial_raw, "embargos infringentes") ~ "Embargos Infringentes",
           #str_detect(classe_judicial_raw, "divergencia") ~ "Embargos de Divergência",
           #str_detect(classe_judicial_raw, "questao de ordem") ~ "Questão de Ordem",
           #str_detect(classe_judicial_raw, "conflito") ~ "Conflito de Competência",
           str_detect(classe_judicial_raw, "^apelacao") ~ "Apelação",
           str_detect(classe_judicial_raw, "acao rescisoria") ~ "Ação Rescisória",
           TRUE ~ "Outros"
                                    ),
         # um formato date do ano do julgamento, para agrupar
         ano_julgamento= lubridate::year(data_julgamento),
         #aproveitei para fazer uma variável
         #tempo entre recurso e julgamento
         autuacao_julgamento = data_julgamento - data_autuacao
         )

Eliminei duplicidade nos assuntos. Tenho os assuntos mais reocrrentes, necessários para minha análise, de forma padronizada.

julgados_28_tidy %>%
  count(classe_judicial) 
##          classe_judicial    n
## 1        Ação Rescisória  475
## 2  Agravo de Instrumento 1758
## 3      Agravo Regimental  716
## 4               Apelação 4690
## 5    Embargos à Execução   61
## 6 Embargos de Declaração  885
## 7                 Outros  155
## 8     Remessa Necessária  341

Tenho as principais variáveis que quero, características dos processos que dividem o gurpo e principalmene o tempo.

julgados_28_tidy %>%
  #filter(classe_judicial == "Ação Rescisória") %>%
  select(numero_processo,
         classe_judicial,
         relator,
         orgao_julgador,
        # referencia,
         data_autuacao,
         data_julgamento,
         autuacao_julgamento,
         ementa
         ) %>%
  glimpse()
## Rows: 9,081
## Columns: 8
## $ numero_processo     <chr> "08032902720154058200", "08077735220214050000", "0~
## $ classe_judicial     <chr> "Apelação", "Agravo de Instrumento", "Apelação", "~
## $ relator             <chr> "DESEMBARGADOR FEDERAL IVAN LIRA DE CARVALHO (CONV~
## $ orgao_julgador      <chr> "3ª TURMA", "3ª TURMA", "3ª TURMA", "3ª TURMA", "4~
## $ data_autuacao       <date> 2015-08-23, 2021-07-02, 2020-11-27, 2021-05-19, 2~
## $ data_julgamento     <date> 2021-09-30, 2021-09-30, 2021-09-30, 2021-09-30, 2~
## $ autuacao_julgamento <drtn> 2230 days, 90 days, 307 days, 134 days, 4201 days~
## $ ementa              <chr> "PROCESSO Nº: 0803290-27.2015.4.05.8200 - APELAÇÃO~

2.4.2 Analisando Tempo e Ano

Esses vários tipos de julgados estão por diversos anos. Nesse ggplot abaixo:

Algo engraçdo é que a partir do novo CPC 2015, não existe mais o agravo regimental. Foi substituído pelo agravo interno… Ainda assim, o número de agravos regimentais julgados depois de 2015 é enorme, demonstrando falha dos dados do tribunal.

Mas o que interessa aqui no meu escritório é a duração dos processos.Vamos então fazer umas contas sobre tempo e datas.

Eu preferi a mediana por ser o padrão ouro da ABJ, já que processos juidiciais tem muitos outliers de grandes números. Mas o pessoal do escritório pediu média e desvio padrão.

julgados_28_tidy %>% 
  group_by(classe_judicial) %>%
  summarise(mediana_julgamento = median(autuacao_julgamento, na.rm = TRUE),
            iqr_julgamento = IQR(autuacao_julgamento, na.rm = TRUE),
            media_julgamento = mean(autuacao_julgamento, na.rm = TRUE),
            desvio_pad_julgamento= sd(autuacao_julgamento, na.rm= TRUE)
            )
## # A tibble: 8 x 5
##   classe_judicial        mediana_julgamento iqr_julgamento media_julgamento
##   <chr>                  <drtn>                      <dbl> <drtn>          
## 1 Ação Rescisória        495 days                     495   637.0159 days  
## 2 Agravo de Instrumento  232 days                     391   389.6841 days  
## 3 Agravo Regimental      293 days                     506.  508.6208 days  
## 4 Apelação               350 days                     743   664.8414 days  
## 5 Embargos à Execução    943 days                     992  1096.5500 days  
## 6 Embargos de Declaração  63 days                     164   230.8520 days  
## 7 Outros                 225 days                     874.  649.4886 days  
## 8 Remessa Necessária     223 days                     590   523.6382 days  
## # ... with 1 more variable: desvio_pad_julgamento <dbl>

Números são ruins. Pessoal de humanas não entende… Nós gostamos de gráficos! Vamos facetar todas essas classes entao.

O foco era nas ações rescisórias, perigosas ações que podem reverter uma ação já transitada em julgado, cuja “decisão é imodificável, transforma o redondo em quadrado”, mas como tudo no Direito tem um depende, elas podiam foder a operação inteira de execuções de decisões já julgadas.

Estavam em voga nos corredores do escritório e fiz, portanto, o tempo médio até seu julgamentos:

Esse foi então o scrapper de jurisprudência do TRF5!

3 Consulta de Processos Físicos

As vezes, tão importante quanto ter as ementas e o inteiro teor das decisões para extrair seu conteúdo, é ter os “metadados” dos processos que elas estão inserdidas. Valor da causa, partes do processo, movimentação. Por isso, temos que buscar também informações de quais processos estão.

No caso tenho uma lista de processos sobre precatórios, um regime de pagamento de dívidas judiciais do Estado. Meu objetivo é baixar todas as movimentações desse processo para ver quanto tempo o Estado leva para pagar você depois de ganhar o processo (leva em geral mais de 10 anos).

O mérito da questão, a tese dos “28,86%” já está considerada como consolidada pelo escritório. Eles querem saber quanto tempo o precatório demora para expedido. Assim, peguei uma lista de 173 processos que foram fornecidos dentro do próprio escritórion no download.

No campo do _arsing, de estrutura física mais antiga cheia de tables. Aqui retorna HTML mesmo, então esse tem mais parsing.

3.1 Vendo como site funciona, Baixando e Iterando

Hoje, na maioria dos tribunais existem dois buscadores de processos. Um de processos físicos, no site principal, e outro no PJE (processo judicial eletrônico), em outro site separado. Assim, se o processo for eletrônico, ele não retornará do buscador do site oficial.

Se você entrar no site pela consulta processual e colocar o número do processo, como um típico formulário, cocê coloca o numero e vai abrir uma janela nova para próxima:

Tela Inicial consulta no site https://cp.trf5.jus.br/cp/index.html

Ela retorna com um POST dessa consulta:

Resposta consulta no site https://cp.trf5.jus.br/cp/cp.do

Engraçado. Eu só me dei conta disso fazendo o markdown. Porque se você acessa por um outro caminho do site, como fiz, um GET muito mais simples funciona, que so adiciona o nuúmero do processo ao final do url base:

url_base <- "https://cp.trf5.jus.br/processo/"

Resposta consulta no https://cp.trf5.jus.br/processo/

Vamos para a mesma página, do mesmo processo, com as mesmas informações, em URL’s diferentes, que só tem url_base / numero do processo. Escolhi portanto o mais simples.

Vamos direto baixar a função. É só ter o numero do processo e dar um paste na url base

trf5_baixar_cpopg <- function(processos = "",
                              diretorio= "") {

  #Criando URL BAse
url_base <- "https://cp.trf5.jus.br/processo/"
    #Criando Barrade Progesso
barra_progresso <- progress::progress_bar $ new(total = length(processos))

      #Listas com números dos processos
map (.x= processos, 
      .f= ~ { 
        
        barra_progresso$tick()
        
        #Paste URL base + True
        httr::GET (paste0(url_base,
                             .x),
                   #Writedisk com numero + data baixada para evitar overwritting
                      httr::write_disk(path = paste0(diretorio, 
                                                     "/",
                                                     "julgados_",
                                                     as.character(.x),
                                                     "_",
                                                     Sys.time()%>%
                                                       stringr::str_replace_all("\\D","_"),
                                                     ".html")
                                       )
                     ) }
      )
 
 
}

A função deu certo. Baixamos 173 processos de precatórios.

#Lista de Processos se quiserem reproduzir


#trf5_baixar_cpopg(processos = processos_precatorios_ind,
 #                diretorio = "cpopg/data_raw")

173 processos de precatórios baixados

3.2 Lendo, Parseando e Iterando

Os HTML’s baixandos são de um site “simples”, todo formatado em sem nome de classe.

Apesar de ter funcionado parsing, ficou bem feio.

Eu tentei pegar por classe, nome ou outras questões, mas era muita coisa igual sem identificação. Por exemplo, quando estava “negrito”, como no caso das movimentações… Algumas partes deu pegar pelas widths das tables, mas chegou no final que teve que fazer purrr::pluck em tudo mesmo.

Todas as tables sem nomes e atributos parecidos

3.2.1 Lendo e Iterando: Dados do Processos

Quero nessa função baixar os dados gerais, para verificar número, orgão julgado, entre outras questões.

O número do processo eu tinha no primeiro header. As demais informações estão nas duas primeiras tabelas de width = 87%, como dá para ver na imagem acima.

trf5_cpo_fisico_ler_processos <- function(diretorio= "") {
  
  # Faça a lista de Arquivos presente na pasta
  arquivos_lista <-   base::list.files(paste0(diretorio,"/"),
                               pattern = "\\.html$", 
                               full.names = TRUE) 
  
  #Faça o tamanho da barra de progresso
  barra_progresso <- progress::progress_bar $ new(total = 
                                                   length(arquivos_lista)
                                                  )
  
  #Leia os Arquivos
   purrr::map_dfr( .x= arquivos_lista,
               .f = ~{
               barra_progresso$tick()
  # um arquivo de todo html
              arquivos_raw <- xml2::read_html (.x)
      
              #o numero do processo         
              processo <- arquivos_raw %>%
                        xml2::xml_find_first("/html/body/p[2]") %>%
                          xml2::xml_text() %>%
                stringr::str_remove("\n      PROCESSO Nº ")
              # tentei extrair a tabela inteira como rows de um df... não deu muito certo 
                prec <- arquivos_raw %>%
                 xml2::xml_find_first("/html/body/table") %>%
                 xml2::xml_find_all("./tr/td") %>%
                 xml_text()
                
              #fiz assim um pluck em cada linha dessa table
                
                n_precatorio <- arquivos_raw %>%
                 xml2::xml_find_first("/html/body/table") %>%
                 xml2::xml_find_all("./tr/td") %>%
                 xml_text() %>% pluck(1) %>%
                  stringr::str_extract("PRC.+\\b")
               
                data_atuacao <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(2) %>%
                    stringr::str_remove("AUTUADO EM ")
              
                orgao <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(3) %>%
                    stringr::str_remove("ORGÃO: ")
                
                n_originario <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(4) %>%
                  stringr::str_remove("PROC. ORIGINÁRIO Nº: ")
                 
                n_requisitorio <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(5) %>%
                  stringr::str_remove("NÚMERO DO REQUISITÓRIO: ")
                
                n_execucao <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(6) %>%
                  stringr::str_remove("NÚMERO DO PROCESSO DE EXECUÇÃO: ")
                
                vara <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(7) %>%
                  stringr::str_remove("VARA: ")
                
                natureza_credito <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(8) %>%
                  stringr::str_remove("CRÉDITO: ")
                
                assunto <- arquivos_raw %>%
                  xml2::xml_find_first("/html/body/table") %>%
                  xml2::xml_find_all("./tr/td") %>%
                  xml_text() %>% pluck(9) %>%
                  stringr::str_remove("ASSUNTO: ")
                
                # Para pegar todas as tabelas e ajudar a ver no inicio
               tabelas <- arquivos_raw %>%
                xml2::xml_find_all("/html/body/table") %>%
                 html_table()
               
               #segunda tabela
               tabelas2 <- arquivos_raw %>%
                 xml2::xml_find_all("/html/body/table[2]") %>%
                 xml2::xml_find_all("./tr/td") %>%
                 xml_text() 
               
               #e as linhas que eu queria
               fase_atual <- tabelas2 %>% pluck(3)
               
               data_fase_atual <- tabelas2 %>% pluck(2)
               
               complemento <- tabelas2 %>% pluck(5)
               
               ultima_localizacao <- tabelas2 %>% pluck(7)
            
               #tibble para fazer de forma organizada
               tibble(processo,
                      n_precatorio,
                      data_atuacao,
                      orgao,
                      n_originario,
                      n_requisitorio,
                      n_execucao,
                      vara,
                      natureza_credito,
                      assunto,
                      fase_atual,
                      data_fase_atual,
                      complemento,
                      ultima_localizacao)
               
               #uma list para ir testando e ver o resultado usada anteriormente
               #list(processo,
                #    prec,
                 #   tabelas,
                  #  tabelas2)
            
  })
  
  
}

Consigo assim uma tabela com informações gerais do processo:

processos_prec <- trf5_cpo_fisico_ler_processos(diretorio = "cpopg/data_raw")

as_tibble(processos_prec)
## # A tibble: 173 x 14
##    processo    n_precatorio data_atuacao  orgao   n_originario    n_requisitorio
##    <chr>       <chr>        <chr>         <chr>   <chr>           <chr>         
##  1 0230135-97~ PRC199202-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  2 0230259-80~ PRC199203-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  3 0230260-65~ PRC199204-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  4 0230261-50~ PRC199205-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  5 0230262-35~ PRC199206-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  6 0230263-20~ PRC199207-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  7 0230264-05~ PRC199208-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  8 0230265-87~ PRC199209-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
##  9 0230266-72~ PRC199210-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
## 10 0230267-57~ PRC199211-PB "\n26/02/202~ Divisã~ 00085286520124~ 2020820000220~
## # ... with 163 more rows, and 8 more variables: n_execucao <chr>, vara <chr>,
## #   natureza_credito <chr>, assunto <chr>, fase_atual <chr>,
## #   data_fase_atual <chr>, complemento <chr>, ultima_localizacao <chr>

3.2.2 Lendo e Iterando: Partes do Processo

Aqui quero saber as partes. Elas estão na única table de altura 52:

Tabela de altura 52 que tinha informação sobre as partes

trf5_cpo_fisico_ler_partes <- function(diretorio= "") {
    
    # Faça a lista de Arquivos presente na pasta
    arquivos_lista <-   base::list.files(paste0(diretorio,"/"),
                                         pattern = "\\.html$", 
                                         full.names = TRUE) 
    
    #Faça o tamanho da barra de progresso
    barra_progresso <- progress::progress_bar $ new(total = 
                                                      length(arquivos_lista)
    )
    
    #Leia os Arquivos
    purrr::map_dfr( .x= arquivos_lista,
                .f = ~{
                  barra_progresso$tick()
                  
                  arquivos_raw <- xml2::read_html (.x)
                  
                  #Uma coluna com processo para identificar
                  processo <- arquivos_raw %>%
                    xml2::xml_find_first("/html/body/p[2]") %>%
                    xml2::xml_text() %>%
                    stringr::str_remove("\n      PROCESSO Nº ")
                  
                  #Buscando a tabela de altura 52
                  #Dados de qual lado do processo ela está
                  tipo_partes <- arquivos_raw %>%
                    xml2::xml_find_first("//table[@height= '52']") %>%
                    rvest::html_table() %>%
                    pluck(1) %>%
                    str_replace("REQDO", "Requerido")%>%
                    str_replace("REQTE", "Requerente")
                  
                  #O nome específico de cada parte
                  partes <- arquivos_raw %>%
                    xml2::xml_find_first("//table[@height= '52']") %>%
                    rvest::html_table() %>%
                    purrr::pluck(2) %>%
                    stringr::str_remove(": (\\t)*")
                  
                  #montando a tibble
                   tibble(processo,
                         tipo_partes,
                         partes) 
                  
                  #list(processo,
                  #     partes)
                  
                })
    
    
}

Consigo assim uma tabela com informações das partes do processo:

partes_prec <- trf5_cpo_fisico_ler_partes(diretorio = "cpopg/data_raw")

as_tibble(partes_prec)
## # A tibble: 1,246 x 3
##    processo                  tipo_partes            partes                      
##    <chr>                     <chr>                  <chr>                       
##  1 0230135-97.2021.4.05.0000 Requerente             MARCOS JACOME DE ALMEIDA    
##  2 0230135-97.2021.4.05.0000 Escritório Advocatício GUEDES PEREIRA & DUARTE - A~
##  3 0230135-97.2021.4.05.0000 Escritório Advocatício JOSE MARIO PORTO & MAIA ADV~
##  4 0230135-97.2021.4.05.0000 Escritório Advocatício MAURO MENEZES & ADVOGADOS   
##  5 0230135-97.2021.4.05.0000 Escritório Advocatício ROCHA, MARINHO E SALES SOCI~
##  6 0230135-97.2021.4.05.0000 Requerido              UFPB - UNIVERSIDADE FEDERAL~
##  7 0230135-97.2021.4.05.0000 Deprecante             JUÍZO DA 2ª VARA FEDERAL DA~
##  8 0230135-97.2021.4.05.0000 RELATOR                DESEMBARGADOR(A) FEDERAL PR~
##  9 0230259-80.2021.4.05.0000 Requerente             CLAUDET COELHO GUEDES       
## 10 0230259-80.2021.4.05.0000 Escritório Advocatício GUEDES PEREIRA & DUARTE - A~
## # ... with 1,236 more rows

3.2.3 Lendo e Iterando: Movimentações do Processo

Aqui está a parte de maior interesse. Todas as movimentações São todas de altura 28 e são as últimas. Mas temos duas tabelas do mesmo tamanho que não são movimentações.

Tabela de altura 28

A solução foi baixar todas de 28 e filtrar os textos, já que todas os textos de movimentação começam com “Em dd/mm/aaaa”.

  trf5_cpo_fisico_ler_movimentacoes <- function(diretorio= "") {
    
    # Faça a lista de Arquivos presente na pasta
    arquivos_lista <-   base::list.files(paste0(diretorio,"/"),
                                         pattern = "\\.html$", 
                                         full.names = TRUE) 
    
    #Faça o tamanho da barra de progresso
    barra_progresso <- progress::progress_bar $ new(total = 
                                                      length(arquivos_lista)
    )
    
    #Leia os Arquivos
    purrr::map_dfr( .x= arquivos_lista,
                .f = ~{
                  barra_progresso$tick()
                  
                  arquivos_raw <- xml2::read_html (.x)
                  
                  #para identificar o processo
                  processo <- arquivos_raw %>%
                    xml2::xml_find_first("/html/body/p[2]") %>%
                    xml2::xml_text() %>%
                    stringr::str_remove("\n      PROCESSO Nº ")
            
                  
                  #tabelas<- arquivos_raw %>%
                   # xml2::xml_find_all("/html/body/table") %>%
                    #html_table()
                  
                  #ate tentei pegar pela classe, uma das únicas com nomes
                  #mas só pegava a data, não o texto inteiro da <tr>
                  data_movimentacoes <- arquivos_raw %>%
                    xml2::xml_find_all("//li[@class='negrito']") %>%
                    xml2::xml_text() %>%
                    stringr::str_extract("\\d+/\\d+/\\d+") %>%
                    lubridate::dmy()
                  
                  # Peguei o texto inteiro
                  movimentacoes <- arquivos_raw %>%
                    xml2::xml_find_all("//table[@height= '28']")%>%
                    xml2::xml_text() 
                  
                  #Fiz a tibble
                 tibble(processo,
                         #data_movimentacoes,
                         movimentacoes) %>%
                   #Filtrei pelas tables que começavam com o padrão de momvimentações
                   dplyr::filter(str_detect(movimentacoes, "Em \\d+/\\d+/\\d+")) %>%
                   #Separando a data movimentação do seu conteúdo
                   tidyr::separate(movimentacoes,
                                   into = c("data_movimentacao", "movimentacao"),
                                    sep= "\\d+:\\d+",
                                   extra = "merge") %>%
                   #transformando em formato date
                   dplyr::mutate(data_movimentacao= stringr::str_extract(data_movimentacao,"\\d+/\\d+/\\d+") %>%
                                   lubridate::dmy()
                   )
                  
                  #list(processo,
                      # tabelas,
                   #    data_movimentacoes,
                    #   movimentacoes)
                  
                })
    
    
  }

Ela leu todas as movimentações de todos os processos. Como era de maior interesse para meu trabalho, vou apresentar inteira aqui. =)

3.3 Usando a Base

Aqui está o interesse do escritório. Ele que saber depois de quanto tempo um precatório, ao ser pedido, leva até que ele seja depositado na conta judicial. Está interessado em saber quanto tempo que leva para o $$$ cair na conta.

A função de análise do tempo dos processsos do José de Jesus ajudou bastante aqui, criando as três últimas colunas.

movimentacoes_prec <- trf5_cpo_fisico_ler_movimentacoes (diretorio = "cpopg/data_raw")  %>%
  JurisMiner::tempo_movimentacao(data = data_movimentacao)

as_tibble(movimentacoes_prec)
## # A tibble: 2,675 x 6
##    processo                  data_movimentac~ movimentacao anterior   decorrencia
##    <chr>                     <date>           <chr>        <date>           <dbl>
##  1 0230135-97.2021.4.05.0000 2021-07-05       "\n\n\n Ins~ 2021-07-02           3
##  2 0230135-97.2021.4.05.0000 2021-07-02       "\n\n\n Atu~ 2021-03-03         121
##  3 0230135-97.2021.4.05.0000 2021-03-03       "\n\n\n Exp~ 2021-03-03           0
##  4 0230135-97.2021.4.05.0000 2021-03-03       "\n\n\n Ret~ 2021-03-02           1
##  5 0230135-97.2021.4.05.0000 2021-03-02       "\n\n\n Des~ 2021-03-01           1
##  6 0230135-97.2021.4.05.0000 2021-03-01       "\n\n\n Con~ 2021-03-01           0
##  7 0230135-97.2021.4.05.0000 2021-03-01       "\n\n\n Jun~ 2021-02-27           2
##  8 0230135-97.2021.4.05.0000 2021-02-27       "\n\n\n Inf~ 2021-02-26           1
##  9 0230135-97.2021.4.05.0000 2021-02-26       "\n\n\n Con~ 2021-02-26           0
## 10 0230135-97.2021.4.05.0000 2021-02-26       "\n\n\n Reg~ 2021-02-26           0
## # ... with 2,665 more rows, and 1 more variable: decorrencia_acumulada <dbl>

3.3.1 Classificando movimentações

Li as movimentações e pude perceber alguns padrões textuais e, assim, classifiquei os algumas questões fundamentais como a inscrição para pagamento e o efetivo depósito.

Todos tiveram sucesso, exceto “Expedição de Ofício”, que é bem genérico e o ofício pode ter literalmente qualquer conteúdo. Essa classificação só seria possível com o autos do processo inteiros em mãos.

Também peguei a data inicial, pois, pelo o que foi dito pela empresa, se ele foi inscrito antes de junho, no primeiro semestre, ou depois, no segundo, a data de pagamento vai para o outro ano.

mov_prec_classificadas <- movimentacoes_prec %>%
  dplyr::mutate(data_inicial = case_when(
    is.na(anterior) ~ data_movimentacao
  )) %>%
  tidyr::fill(data_inicial,
              .direction= "up") %>% 
  mutate(tipo_movimentacao =case_when(
    str_detect(movimentacao, "(?i)individualiza[çc][ãa]o") ~ "Cadastro do Precatório",
    str_detect(movimentacao, "(?i)arquivad") ~ "Arquivado",
    str_detect(movimentacao, "(?i)atualiza[cç][aã]o") ~ "Atualização de Valores",
    str_detect(movimentacao, "(?i)dep[oó]sito em conta|(?i)dep[oó]sito efetivado") ~ "Depósito dos Valores",
    str_detect(movimentacao, "(?i)atualiza[cç][aã]o") ~ "Atualização de Valores",
    str_detect(movimentacao, "(?i)instituição") ~ "Indicação do banco para pagamento",
    str_detect(movimentacao, "(?i)exclus[ãa]o|excluir") ~ "Exclusão da Restrição",
    #str_detect(movimentacao, "(?i)expedição de ofício") ~ "Expedição de Ofício",
    str_detect(movimentacao, "(?i)pagamento em processamento") ~ "Pagamento em Processamento",
    str_detect(movimentacao, "Precatório foi inscrito para pagamento em 2021") ~ "Inscrito para Pagamento em 2021",
    str_detect(movimentacao, "(?i)precatório sera inscrito para pagto em 2022") ~ "Inscrito para Pagamento em 2022"),
    mes_inicial= lubridate::month(data_inicial),
    ano_inicial= lubridate::year(data_inicial),
    md_inicial= as.character(data_inicial)%>% 
      stringr::str_replace("\\d{2,2}$", "01") %>%
      lubridate::ymd()
  )

3.3.2 Contando por Tipo de Despacho.

Com isso, conseguir responder a respota de que, por exemplo,:

Quanto tempo leva em média para que depois de cadastrado o precatório, seus valores sejam atualizados e assim depositados na conta judicial?

Agrupei essas resposta por ano e mês inicial.

count_class <- mov_prec_classificadas%>%
  filter(tipo_movimentacao != is.na(tipo_movimentacao))%>%
  group_by(tipo_movimentacao, md_inicial) %>%
      summarise(media_ultima_mov_inic = mean(decorrencia_acumulada) %>% as.integer(),
                desv_padrao_ultima_mov_inic =  sd(decorrencia_acumulada),
                mediana_ultima_mov_inic = median(decorrencia_acumulada) %>% as.integer(),
                iqr_distancia_mediana =  IQR(decorrencia_acumulada)
                )%>%
  arrange(desc(media_ultima_mov_inic))%>%
  mutate(dias_desde_inicio=  lubridate::days(media_ultima_mov_inic),
         data_media_ultimo_despacho = md_inicial + lubridate::days(media_ultima_mov_inic))
## `summarise()` has grouped output by 'tipo_movimentacao'. You can override using the `.groups` argument.

Só para apresentar por Mês por Ano dos precatórios, de forma mais organizada:

count_class%>%
  filter(md_inicial == "2020-06-01" )
## # A tibble: 7 x 8
## # Groups:   tipo_movimentacao [7]
##   tipo_movimentac~ md_inicial media_ultima_mo~ desv_padrao_ult~ mediana_ultima_~
##   <chr>            <date>                <int>            <dbl>            <int>
## 1 Arquivado        2020-06-01              413             7.66              416
## 2 Depósito dos Va~ 2020-06-01              368             6.64              365
## 3 Pagamento em Pr~ 2020-06-01              357             6.49              354
## 4 Atualização de ~ 2020-06-01              231             6.49              228
## 5 Indicação do ba~ 2020-06-01              231             6.49              228
## 6 Inscrito para P~ 2020-06-01               13             6.49               10
## 7 Cadastro do Pre~ 2020-06-01                0             0                   0
## # ... with 3 more variables: iqr_distancia_mediana <dbl>,
## #   dias_desde_inicio <Period>, data_media_ultimo_despacho <date>
count_class %>%
  filter(md_inicial == "2020-07-01" )
## # A tibble: 7 x 8
## # Groups:   tipo_movimentacao [7]
##   tipo_movimentac~ md_inicial media_ultima_mo~ desv_padrao_ult~ mediana_ultima_~
##   <chr>            <date>                <int>            <dbl>            <int>
## 1 Depósito dos Va~ 2020-07-01              362            0.501              362
## 2 Pagamento em Pr~ 2020-07-01              352            0                  352
## 3 Exclusão da Res~ 2020-07-01              243            2.20               244
## 4 Atualização de ~ 2020-07-01              239           38.6                226
## 5 Indicação do ba~ 2020-07-01              239           38.6                226
## 6 Inscrito para P~ 2020-07-01                8            0                    8
## 7 Cadastro do Pre~ 2020-07-01                0            0                    0
## # ... with 3 more variables: iqr_distancia_mediana <dbl>,
## #   dias_desde_inicio <Period>, data_media_ultimo_despacho <date>
count_class%>%
  filter(md_inicial == "2021-02-01" )
## # A tibble: 5 x 8
## # Groups:   tipo_movimentacao [5]
##   tipo_movimentac~ md_inicial media_ultima_mo~ desv_padrao_ult~ mediana_ultima_~
##   <chr>            <date>                <int>            <dbl>            <int>
## 1 Indicação do ba~ 2021-02-01              129            0                  129
## 2 Atualização de ~ 2021-02-01              126            0                  126
## 3 Exclusão da Res~ 2021-02-01                4            0.512                4
## 4 Inscrito para P~ 2021-02-01                1            0                    1
## 5 Cadastro do Pre~ 2021-02-01                0            0                    0
## # ... with 3 more variables: iqr_distancia_mediana <dbl>,
## #   dias_desde_inicio <Period>, data_media_ultimo_despacho <date>

3.3.3 Últimas Movimentações

Quero aqui somente as ultimas movimentações de cada processo, falar o estágio atual do processo.

mov_prec_ultimas <- mov_prec_classificadas %>%
  group_by(processo) %>%
  filter(decorrencia_acumulada == max(decorrencia_acumulada)) %>%
  distinct(processo, .keep_all = TRUE) %>%
  ungroup(processo) %>%
  mutate(
    md_final= as.character(data_movimentacao)%>% 
      stringr::str_replace("\\d{2,2}$", "01") %>%
      lubridate::ymd()
  )


mov_prec_ultimas%>%
  count(md_inicial)
## # A tibble: 3 x 2
##   md_inicial     n
##   <date>     <int>
## 1 2020-06-01    72
## 2 2020-07-01    90
## 3 2021-02-01    11
mov_prec_ultimas%>%
  group_by(tipo_movimentacao,
           md_inicial) %>%
  summarise(media_ultima_mov_inic = mean(decorrencia_acumulada),
            desv_padrao_ultima_mov_inic =  sd(decorrencia_acumulada),
            mediana_ultima_mov_inic = median(decorrencia_acumulada)%>%
              as.integer(),
            iqr_distancia_mediana =  IQR(decorrencia_acumulada))%>%
  arrange(desc(media_ultima_mov_inic))
## `summarise()` has grouped output by 'tipo_movimentacao'. You can override using the `.groups` argument.
## # A tibble: 5 x 6
## # Groups:   tipo_movimentacao [4]
##   tipo_movimentac~ md_inicial media_ultima_mo~ desv_padrao_ult~ mediana_ultima_~
##   <chr>            <date>                <dbl>            <dbl>            <int>
## 1 <NA>             2020-06-01             422.             1.98              421
## 2 <NA>             2020-07-01             412.             1.44              412
## 3 Arquivado        2020-06-01             411.             7.88              406
## 4 Depósito dos Va~ 2020-07-01             363              0                 363
## 5 Indicação do ba~ 2021-02-01             129              0                 129
## # ... with 1 more variable: iqr_distancia_mediana <dbl>

Era interessante aqui fazer um fluxograma para o pessoal do escritório entender, além de que sinceramente nem sei se dá para fazer isso no R.

Peguei esses dados e assim os fiz.

Fluxograma apresentado no escritório

Dos precatórios em poder do escritório dentro dessa ação, os de Julho/20 já foram expedidos e levaram 429 dias. Os de Junho/20 estão em fase final, com 369 dias, já que nenhum consta “Arquivamento Definitivo”.

Se der para fazer essa conta de padaria, os de Fev/21 devem demorar algo em torno de duzentos dias para sair… Não tenho dados de Fev/20 para ver se a tese do escritório de que o mês de inscrição faz diferença no tempo de expedição dos precatórios está correta ou não.

4 Finalizando

Apesar de estár aí uns 2 para três meses atrasado com curso, várias coisas aconteceram aí no meio, prova da OAB, troca de escritório, estou extremamente feliz com o resultado.

Eu sempre “soube” como WebScrapping funcionava mas na hora H, o projeto travava, meu chefe me pressionava e os resultados nunca vinham.

Aprender isso me parece ter sido um importante passo nessa minha caminhada pela jurimetria e tentar baixar dados de tribunais.

Muito obrigado Julio, Caio e à toda Curso R. Espero que tenham gostado. Perdão pelo pequeno atraso causado por questões profissionais, prova da OAB, troca de escritório e TDAH.